﻿using System.Runtime.Remoting.Messaging;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NHibernate;
using NHibernate.Cfg;

namespace Lucid.ESA.ClientDataSystem.Data.Common
{
    /// <summary>
    /// Class for providing NHibernate Session objects.
    /// </summary>
    public static class SessionProvider
    {
        private const string SESSION_KEY = "CONTEXT_SESSION";
        private static ISessionFactory _sessionFactory;
        private static ISession _session;
        public static TestContext CurrentTestContext;

        /// <summary>
        /// Reads config and builds SessionFactory.
        /// </summary>
        private static void Init()
        {
            Configuration configuration = new Configuration();
            configuration.Configure();
            configuration.AddAssembly(typeof(SessionProvider).Assembly.GetName().Name);
            log4net.Config.XmlConfigurator.Configure();
            _sessionFactory = configuration.BuildSessionFactory();
        }

        private static ISession ContextSession
        {
            get
            {
                if (CurrentTestContext != null)
                {
                    if (CurrentTestContext.Properties.Contains(SESSION_KEY))
                        return (ISession)CurrentTestContext.Properties[SESSION_KEY];
                    else
                        return null;
                }
                else if (HttpContext.Current != null)
                {
                    return (ISession)HttpContext.Current.Items[SESSION_KEY];
                }
                else
                {
                    return (ISession)CallContext.GetData(SESSION_KEY);
                }
            }
            set
            {
                if (CurrentTestContext != null)
                {
                    if (!CurrentTestContext.Properties.Contains(SESSION_KEY))
                        CurrentTestContext.Properties.Add(SESSION_KEY, value);
                    else
                        CurrentTestContext.Properties[SESSION_KEY] = value;
                }
                else if (HttpContext.Current != null)
                {
                    HttpContext.Current.Items[SESSION_KEY] = value;
                }
                else 
                {
                    CallContext.SetData(SESSION_KEY, value);
                }
            }
        }

        private static ISessionFactory GetSessionFactory()
        {
            if (_sessionFactory == null)
                Init();

            return _sessionFactory;
        }

        private static ISession GetNewSession()
        {
            return GetSessionFactory().OpenSession();
        }

        public static ISession GetCurrentSession()
        {
            _session = ContextSession;

            if (_session == null)
            {
                _session = GetNewSession();
                ContextSession = _session;
            }       

            return _session;
        }

        public static void CloseSession()
        {
            if (_session != null) _session.Close();
            _session = null;

            if (CurrentTestContext != null && CurrentTestContext.Properties.Contains(SESSION_KEY))
                CurrentTestContext.Properties.Remove(SESSION_KEY);
            else if (HttpContext.Current != null && HttpContext.Current.Items.Contains(SESSION_KEY))
                HttpContext.Current.Items.Remove(SESSION_KEY);
            else 
                CallContext.SetData(SESSION_KEY, null);
        }
    }
}